home *** CD-ROM | disk | FTP | other *** search
- /*
- * curses.c
- *
- * Stdscr Curses for PC Class Machines.
- *
- * Copyright 1990, 1993 by Anthony Howe. All rights reserved. No warranty.
- *
- *
- * DESCRIPTION:
- * This is a quick and dirty curses. It assumes that only stdscr is
- * used and so writes directly to the screen via the bios rather than
- * wait for a refresh().
- */
-
- #include <dos.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include "curses.h"
- #include "unctrl.h"
-
- #define ISFUNCKEY(x) (0x100 <= (x))
-
- SCREEN _tty;
- WINDOW _stdscr;
- chtype A_NORMAL;
- chtype A_REVERSE;
-
- WINDOW *
- initscr()
- {
- int i;
-
- _tty.mode = GetVideoMode();
- _tty.page = GetDisplayPage();
- _stdscr.mcol = _tty.width = GetScreenWidth();
-
- switch (_tty.mode) {
- case 0:
- case 1:
- case 2:
- case 3:
- /* Common colour modes. */
- _stdscr.mrow = _tty.height = SCREEN_HEIGHT;
- _tty.seg = 0xb800;
- break;
- case 7:
- /* Common monochrome mode. */
- _stdscr.mrow = _tty.height = SCREEN_HEIGHT;
- _tty.seg = 0xb000;
- break;
- default:
- return (NULL);
- }
-
- /* Fetch screen attributes from bottom-left corner. */
- mvcur(-1, -1, _tty.height-1, 0);
- A_NORMAL = GetChtype(_tty.page) & A_ATTRIBUTES;
- A_REVERSE = ((A_NORMAL & 0x0700) << 4) | ((A_NORMAL & 0xf000) >> 4);
-
- _stdscr.attr = A_NORMAL;
- _stdscr.back = A_NORMAL | ' ';
- _stdscr.flags |= _FULLWIN;
- _stdscr.row = _stdscr.col = _stdscr.brow = _stdscr.bcol = 0;
-
- /* Create a dynamic array. */
- _stdscr.display = (chtype far **) malloc
- (_tty.height * sizeof (chtype far *)
- );
- if (_stdscr.display == NULL)
- return (NULL);
-
- _stdscr.display[0] = MK_FP(_tty.seg, 0);
- _stdscr.flags |= _MEMMAP;
-
- for (i = 1; i < LINES; ++i)
- _stdscr.display[i] = _stdscr.display[i-1] + _tty.width;
-
- clear();
- echo();
- nl();
- scrollok(stdscr, FALSE);
- return (&_stdscr);
- }
-
- int
- addch(c)
- chtype c;
- {
- int n;
-
- switch (c) {
- case '\t':
- n = 8-(_stdscr.col&7);
- while (0 < n--)
- addch(' ');
- break;
- case '\r':
- _stdscr.col = 0;
- break;
- case '\n':
- clrtoeol();
- if (_tty._crlf)
- _stdscr.col = 0;
- ++_stdscr.row;
- break;
- case '\b':
- if (0 < _stdscr.col)
- --_stdscr.col;
- else if (0 < _stdscr.row)
- --_stdscr.row;
- break;
- default:
- c |= _stdscr.attr;
- if (_stdscr.display[_stdscr.row][_stdscr.col] != c) {
- _stdscr.display[_stdscr.row][_stdscr.col] = c;
- }
- ++_stdscr.col;
- }
- if (COLS <= _stdscr.col) {
- _stdscr.col = 0;
- ++_stdscr.row;
- }
- if (LINES <= _stdscr.row && (_stdscr.flags & _SCROLLOK)) {
- /* Scroll up one line. */
- ScrollUp(1, _stdscr.back, 0, 0, LINES, COLS);
- move(LINES-1, 0);
- clrtoeol();
- }
-
- return (OK);
- }
-
- int
- addnstr(s, n)
- char *s;
- int n;
- {
- if (n < 0)
- n = strlen(s);
- while (0 < n-- && *s)
- addch(*s++);
- while (0 < n--)
- addch(' ');
- return (OK);
- }
-
- #ifdef __STDC__
- int
- printw(char *fmt, ...)
- #else
- int
- printw(fmt)
- char *fmt;
- #endif /* __STDC__ */
- {
- int i;
- va_list args;
- va_start(args, fmt);
- i = vwprintw(stdscr, fmt, args);
- va_end(args);
- return (i);
- }
-
- #ifdef __STDC__
- int
- mvprintw(int row, int col, char *fmt, ...)
- #else
- int
- mvprintw(row, col, fmt)
- int row, col;
- char *fmt;
- #endif /* __STDC__ */
- {
- int i;
- va_list args;
- move(row, col);
- va_start(args, fmt);
- i = vwprintw(stdscr, fmt, args);
- va_end(args);
- return (i);
- }
-
- int
- vwprintw(w, fmt, args)
- WINDOW *w;
- char *fmt;
- va_list args;
- {
- int i;
- char buffer[BUFSIZ];
- i = vsprintf(buffer, fmt, args);
- addstr(buffer);
- return (i);
- }
-
- int
- beep()
- {
- AddChar(_tty.page, 7);
- mvcur(-1, -1, _stdscr.row, _stdscr.col);
- return (OK);
- }
-
- int
- endwin()
- {
- chtype blank = ' ' | A_NORMAL;
- mvcur(-1, -1, _tty.height-1, 0);
- PutChtype(_tty.page, blank);
- return (OK);
- }
-
- int
- clrtobot()
- {
- int row, col;
-
- if (LINES <= _stdscr.row)
- return (ERR);
- getyx(stdscr, row, col);
- do {
- if (clrtoeol() == ERR)
- return (ERR);
- _stdscr.col = 0;
- } while (++_stdscr.row < LINES);
- move(row, col);
- return (OK);
- }
-
- int
- clrtoeol()
- {
- register int i;
- register chtype far *ptr;
-
- if (COLS <= _stdscr.col)
- return (ERR);
- ptr = &_stdscr.display[_stdscr.row][_stdscr.col];
- for (i = _stdscr.col; i < COLS; ++i, ++ptr) {
- if (*ptr != _stdscr.back) {
- for (; i < COLS; ++i, ++ptr)
- *ptr = _stdscr.back;
- break;
- }
- }
- return (OK);
- }
-
- int
- refresh()
- {
- if (!(_stdscr.flags & _LEAVEOK))
- mvcur(-1, -1, _stdscr.row, _stdscr.col);
- _stdscr.flags &= ~_CLEAROK;
- return (OK);
- }
-
- int
- clearok(w, bf)
- WINDOW *w;
- int bf;
- {
- if (bf)
- _stdscr.flags |= _CLEAROK;
- else
- _stdscr.flags &= ~_CLEAROK;
- return (OK);
- }
-
- int
- idlok(w, bf)
- WINDOW *w;
- int bf;
- {
- if (bf)
- _stdscr.flags |= _IDLOK;
- else
- _stdscr.flags &= ~_IDLOK;
- return (OK);
- }
-
- int
- scrollok(w, bf)
- WINDOW *w;
- int bf;
- {
- if (bf)
- _stdscr.flags |= _SCROLLOK;
- else
- _stdscr.flags &= ~_SCROLLOK;
- return (OK);
- }
-
- int
- keypad(w, bf)
- WINDOW *w;
- int bf;
- {
- if (bf)
- _stdscr.flags |= _KEYPAD;
- else
- _stdscr.flags &= ~_KEYPAD;
- return (OK);
- }
-
- int
- leaveok(w, bf)
- WINDOW *w;
- int bf;
- {
- if (bf)
- _stdscr.flags |= _LEAVEOK;
- else
- _stdscr.flags &= ~_LEAVEOK;
- return (OK);
- }
-
- int
- getch()
- {
- KEY c;
- refresh();
- if (_stdscr.flags & _KEYPAD) {
- c.val = GetKey();
- if (c.key.ascii == 0) {
- c.key.ascii = c.key.extended;
- c.key.extended = 0x01;
- } else {
- c.key.extended = 0;
- if (_tty._echo)
- addch(c.key.ascii);
- }
- } else {
- static int scancode;
- if (scancode != 0) {
- /* Return previous saved scancode. */
- c.val = scancode;
- scancode = 0;
- } else {
- c.val = GetKey();
- if (c.key.ascii == 0) {
- /* Remember scancode for next call
- * of getch(). Return ^[ this call.
- */
- c.key.ascii = 0x1b;
- scancode = c.key.extended;
- }
- c.key.extended = 0;
- if (_tty._echo)
- addch(c.key.ascii);
- }
- }
- return (c.val);
- }
-
- char *
- unctrl(ch)
- int ch;
- {
- static char buf[5];
- static char *ctrls[] = {
- "^?",
- "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G",
- "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O",
- "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
- "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
- };
- if (ch == 0x7f) {
- return (ctrls[0]);
- } else if (0x7f < ch) {
- (void) sprintf(buf, "\\%03o", ch);
- } else if (iscntrl(ch)) {
- return (ctrls[ch+1]);
- } else {
- *buf = ch;
- buf[1] = '\0';
- }
- return (buf);
- }
-
- typedef struct key_entry_t {
- int code;
- int (*func)(void);
- } key_entry_t;
-
- static int fld_done(void);
- static int fld_erase(void);
- static int fld_kill(void);
- static int fld_left(void);
- static int fld_insert(void);
-
- static key_entry_t table[] = {
- { '\b', fld_erase },
- { CTRL('x'), fld_kill },
- { '\r', fld_done },
- { '\n', fld_done },
- { KEY_LEFT, fld_erase },
- { KEY_BACKSPACE, fld_erase },
- { -1, fld_insert }
- };
-
- static int fld_row;
- static int fld_col;
- static int fld_key;
- static int fld_echo;
- static int fld_index;
- static int fld_length;
- static char *fld_buffer;
-
- int
- getnstr(buf, len)
- char *buf;
- int len;
- {
- key_entry_t *k;
-
- fld_index = 0;
- fld_buffer = buf;
- fld_length = len < 0 ? COLS : len;
- if (--fld_length < 1)
- return (ERR);
- getyx(stdscr, fld_row, fld_col);
- fld_echo = _tty._echo;
- noecho();
-
- for (;;) {
- fld_key = getch();
- for (k = table; k->code != -1 && k->code != fld_key; ++k)
- ;
- if (k->func != NULL && !(k->func)()) {
- fld_buffer[fld_index] = '\0';
- break;
- }
- }
-
- if (fld_echo)
- echo();
- return (OK);
- }
-
- static int
- fld_done()
- {
- return (FALSE);
- }
-
- static int
- fld_left()
- {
- int row, col, max_row, max_col;
-
- getyx(stdscr, row, col);
- getmaxyx(stdscr, max_row, max_col);
- if (0 < fld_index) {
- --fld_index;
- /* Assume that if 0 < fld_index then fld_row <= row
- * and fld_col < col. So when fld_index == 0, then
- * fld_row == row and fld_col == col.
- */
- if (0 < col) {
- --col;
- } else if (0 < row) {
- /* Handle reverse line wrap. */
- --row;
- col = max_col-1;
- }
- move(row, col);
- }
- return (TRUE);
- }
-
- static int
- fld_erase()
- {
- int row, col;
-
- if (0 < fld_index) {
- fld_left();
- getyx(stdscr, row, col);
- addch(' ');
- move(row, col);
- fld_buffer[fld_index] = '\0';
- }
- return (TRUE);
- }
-
- static int
- fld_kill()
- {
- move(fld_row, fld_col);
- while (0 < fld_index--)
- addch(' ');
- move(fld_row, fld_col);
- fld_buffer[0] = '\0';
- fld_index = 0;
- return (TRUE);
- }
-
- static int
- fld_insert()
- {
- if (fld_index < fld_length) {
- if (!ISFUNCKEY(fld_key)) {
- fld_buffer[fld_index++] = fld_key;
- if (fld_echo)
- addch(fld_key);
- } else {
- beep();
- }
- }
- return (fld_index < fld_length);
- }
-
-